package it.prova.transform;

import it.prova.Consts;
import it.prova.Utility;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;

import nu.xom.Attribute;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Nodes;
import nu.xom.ParsingException;
import nu.xom.Text;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.IFileSystem;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jst.pagedesigner.dtmanager.converter.operations.AbstractTransformOperation;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class EntryUnitTransformOperation extends AbstractTransformOperation
{	
	private Document currentModel;
	
	public Element transform(Element sourceElement, Element displayElement)
	{
		if(tagConverterContext == null)
		{
			return displayElement;
		}
		
		String name = sourceElement.getAttribute(Consts.MODEL_ATTRIBUTE_NAME);
		String type = sourceElement.getAttribute(Consts.MODEL_ATTRIBUTE_TYPE);
		
		Element firstElement = null;
		if(Consts.TAG_LABEL_NAME.equals(sourceElement.getLocalName()))
		{
			String fieldName = Utility.getEntryUnitFieldName(name);
			if(fieldName != null)
			{
				firstElement = tagConverterContext.createElement("p");
				
				firstElement.appendChild(tagConverterContext.createText(fieldName));
			}
			else
			{
				firstElement = tagConverterContext.createElement("p");
				
				firstElement.appendChild(tagConverterContext.createText
				(
					"<" + sourceElement.getPrefix() + ":" +
					sourceElement.getLocalName() + " />"
				));
			}
		}
		else if(Consts.TAG_VALUE_NAME.equals(sourceElement.getLocalName()))
		{
			//String fieldType;
			if(type != null)
			{
				if(Consts.FIELD_TYPE_FIELD.equals(type))
				{
					firstElement = tagConverterContext.createElement("input");
					firstElement.setAttribute("type", "text");
				}
				else if(Consts.FIELD_TYPE_MULTI_SELECTION_FIELD.equals(type))
				{
					firstElement = tagConverterContext.createElement("form");
	//				firstElement.setAttribute("type", "checkbox");
					
	//				Element checkbox = tagConverterContext.createElement("input");
	//				checkbox.setAttribute("type", "checkbox");
					
	//				Element br = tagConverterContext.createElement("br");
	//				
	//				checkbox.appendChild(tagConverterContext.createText("pippo"));
	//				firstElement.appendChild(checkbox);
	//				firstElement.appendChild(br);
					
					for(int i=0; i<5; i++)
					{
	//					tagConverterContext.copyChildren(sourceElement, firstElement);
						
						Element checkbox = tagConverterContext.createElement("input");
						checkbox.setAttribute("type", "checkbox");
						
						Element br = tagConverterContext.createElement("br");
						
						firstElement.appendChild(checkbox);
						firstElement.appendChild(br);
					}
				}
				else if(Consts.FIELD_TYPE_SELECTION_FIELD.equals(type))
				{
					firstElement = tagConverterContext.createElement("select");
				}
			}
			else
			{
				firstElement = tagConverterContext.createElement("p");
				
				firstElement.appendChild(tagConverterContext.createText
				(
					"<" + sourceElement.getPrefix() + ":" +
					sourceElement.getLocalName() + " />"
				));
			}
		}
		else if(Consts.TAG_LINK_NAME.equals(sourceElement.getLocalName()))
		{
			firstElement = tagConverterContext.createElement("input");
			firstElement.setAttribute("title", sourceElement.getAttribute(Consts.TAG_ATTRIBUTE_VALUE));
			firstElement.setAttribute("type", "submit");
			firstElement.setAttribute("value", sourceElement.getAttribute(Consts.TAG_ATTRIBUTE_VALUE));
		}
		
		if("".equals(""))
		{
			return firstElement;
		}
				
		Element firstDiv = tagConverterContext.createElement("webratio");
		Element secondDiv = tagConverterContext.createElement("webratio");
		
		currentModel = Utility.getCurrentModel(Consts.MULTI_DATA_UNIT);
		
		if(currentModel != null)
		{
			Nodes attributes = currentModel.query
			(
				Consts.MODEL_ATTRIBUTE_QUERY + "[@" + Consts.MODEL_ENTITY_ATTRIBUTE_NAME + "=\"" + Utility.getEntityName(currentModel) + 
				"\"]/" + Consts.MODEL_ATTRIBUTE_TAG + "[@" + Consts.MODEL_ATTRIBUTE_NAME + "=\"" + name + "\"]/" + 
				sourceElement.getLocalName()
			);
			
			nu.xom.Element attribute = null;
			if(attributes.size() > 1)
			{
				System.out.println("More than one tag with '" + name + "' value for '" + Consts.MODEL_ATTRIBUTE_NAME + "' attribute in current model");
			}
			else if(attributes.size() <= 0)
			{
				// if not found in current model, I have to search in default model
				Document doc = null;
				try
				{
					IFileSystem fileSystem = EFS.getLocalFileSystem();
					IFileStore defaultTemplateFileStore = fileSystem.getStore(URI.create(Consts.MULTI_DATA_UNIT_MODEL_FILE_PATH));
					
					Builder parser = new Builder();
					doc = parser.build(new BufferedInputStream(defaultTemplateFileStore.openInputStream(EFS.NONE, null)));
				}
				catch(CoreException ce)
				{
					ce.printStackTrace();
				}
				catch(IOException ioe)
				{
					ioe.printStackTrace();
				}
				catch(ParsingException pe)
				{
					pe.printStackTrace();
				}
				
				Nodes attributesIn = doc.query
				(
					Consts.MODEL_ATTRIBUTE_QUERY + "[@" + Consts.MODEL_ENTITY_ATTRIBUTE_NAME + "=\"" + Utility.getEntityName(currentModel) + 
					"\"]/" + Consts.MODEL_ATTRIBUTE_TAG + "[@" + Consts.MODEL_ATTRIBUTE_NAME + "=\"" + name + "\"]/" + 
					sourceElement.getLocalName()
				);
				
				if(attributesIn.size() > 1)
				{
					System.out.println("More than one tag with '" + name + "' value for '" + Consts.MODEL_ATTRIBUTE_NAME + "' attribute in default model");
				}
				else if(attributesIn.size() <= 0)
				{
					System.out.println("No tag with '" + name + "' value for '" + Consts.MODEL_ATTRIBUTE_NAME + "' attribute in default model");
				}
				else
				{
					attribute = (nu.xom.Element) attributesIn.get(0);
				}
			}
			else
			{
				// found in current model
				attribute = (nu.xom.Element) attributes.get(0);
			}
			
			if(attribute != null)
			{
				String value = attribute.getValue().trim();
				
				if((value != null) && (value.length() > 0))
				{
					System.out.println("value = " + value);
					System.out.println("sourceElement.getLocalName() = " + sourceElement.getLocalName());
					if(Consts.TAG_VALUE_NAME.equals(sourceElement.getLocalName()))
					{
						Attribute typeAttr = ((nu.xom.Element) attribute.getParent()).getAttribute(Consts.MODEL_ATTRIBUTE_TYPE);
						
						if(typeAttr != null)
						{
							String typeVal = typeAttr.getValue();
							if(Consts.ATTRIBUTE_TYPE_STRING.equals(typeVal))
							{
								value = value.replaceAll(Consts.WR_PLACE_HOLDER_ESCAPED, "abcdefghil");
							}
							else if(Consts.ATTRIBUTE_TYPE_INT.equals(typeVal))
							{
								value = value.replaceAll(Consts.WR_PLACE_HOLDER_ESCAPED, "1234567890");
							}
							else if(Consts.ATTRIBUTE_TYPE_DATE.equals(typeVal))
							{
								value = value.replaceAll(Consts.WR_PLACE_HOLDER_ESCAPED, "31/12/2010");
							}
							else if(Consts.ATTRIBUTE_TYPE_PASSWORD.equals(typeVal))
							{
								value = value.replaceAll(Consts.WR_PLACE_HOLDER_ESCAPED, "**********");
							}
						}
					}
					else if(Consts.TAG_LABEL_NAME.equals(sourceElement.getLocalName()))
					{
						value = value.replaceAll(Consts.WR_PLACE_HOLDER_ESCAPED, sourceElement.getAttribute(Consts.MODEL_ATTRIBUTE_NAME));
					}
					
					Document xom = null;
					try
					{
						Builder parser = new Builder();
						xom = parser.build(new ByteArrayInputStream(value.getBytes()));
					}
					catch(Exception e)
					{
						
					}
					
					if(xom != null)
					{
						nu.xom.Element root = xom.getRootElement();
						
						Element elem = getElementsFromXOM(root);
						
						NodeList nodes = elem.getChildNodes();
						for(int i=0; i<nodes.getLength(); i++)
						{
							secondDiv.appendChild(nodes.item(i));
						}
					}
					else
					{
						org.w3c.dom.Text textvalue = tagConverterContext.createText(value);
						secondDiv.appendChild(textvalue);
					}
				}
			}
			
			// default behaviour
			if(secondDiv.getChildNodes().getLength() == 0)
			{
				Element p = tagConverterContext.createElement("p");
				
				p.appendChild(tagConverterContext.createText
				(
					"<" + sourceElement.getPrefix() + ":" +
					sourceElement.getLocalName() + " />"
				));
				
				secondDiv.appendChild(p);
			}
			tagConverterContext.copyChildren(sourceElement, secondDiv);
		}
		
		firstDiv.appendChild(secondDiv);
		
		return firstDiv;
	}
	
	private Element getElementsFromXOM(nu.xom.Element element)
	{
		Element resultElement = tagConverterContext.createElement(element.getLocalName());
		
		for(int i=0; i<element.getAttributeCount(); i++)
		{
			Attribute attr = element.getAttribute(i);
			resultElement.setAttribute(attr.getLocalName(), attr.getValue());
		}
		
		for(int i=0; i<element.getChildCount(); i++)
		{
			nu.xom.Node node = element.getChild(i);
			
			if(node instanceof nu.xom.Element)
			{
				nu.xom.Element e = (nu.xom.Element) node;
				
				resultElement.appendChild(getElementsFromXOM(e));
			}
			else if(node instanceof nu.xom.Document)
			{
				nu.xom.Document d = (nu.xom.Document) node;
				nu.xom.Element e = d.getRootElement();
				
				resultElement.appendChild(getElementsFromXOM(e));
			}
			else if(node instanceof nu.xom.Text)
			{
				Text t = (Text) node;
				String s = t.getValue();
				
				resultElement.appendChild(tagConverterContext.createText(s));
			}
			else if(node instanceof nu.xom.Comment)
			{
				// skipping comments
			}
			else if(node instanceof nu.xom.Attribute)
			{
				Attribute a = (Attribute) node;
				
				resultElement.setAttribute(a.getLocalName(), a.getValue());
			}
			else if(node instanceof nu.xom.ProcessingInstruction)
			{
				// skipping processing instructions
			}
			else if(node instanceof nu.xom.DocType)
			{
				// skipping document type declarations
			}
			else if(node instanceof nu.xom.Namespace)
			{
				// skipping namespaces
			}
		}
		return resultElement;
	}
}